#include <iostream>
#include <iomanip>
#include <fstream>
#include <vector>
#include <mpi.h>

using namespace std;

// Define a structure for storing x,y cooridnates
typedef struct
{
	double x, y;
} Coord_t;

struct Range
{
	int zeroToOne, oneToTwo, twoToFive, greaterThanFive;
	Range() : zeroToOne( 0 ), oneToTwo( 0 ), twoToFive( 0 ), greaterThanFive( 0 ) { }
};

vector<Coord_t> vFoodBanks;


int main( int argc, char* argv[] ) {
	string residence_fname = "C:/residences.dat";
	string foodbank_fname = "C:/foodbanks.dat";
	int nAddresses = 0;
	Range ranges;

	if( MPI_Init( &argc, &argv ) == MPI_SUCCESS ) {
		// Get # of procs, rank
		int numProcs, rank;
		MPI_Comm_size( MPI_COMM_WORLD, &numProcs );
		MPI_Comm_rank( MPI_COMM_WORLD, &rank );

		//read in food bank data
		ifstream in( foodbank_fname );

		while( !in.eof() ) {
			Coord_t bank;
			in >> bank.x >> bank.y;
			vFoodBanks.push_back( bank );
		}

		//read in residential data
		in.clear();
		in.close();
		in.open( residence_fname );
		while( !in.eof() ) {
			nAddresses++;
			double x,y;
			in >> x >> y;

			//temp ranges
			Range temp;
			temp.zeroToOne = 0;

			//find distance to nearest foodbank
			for( int i = 0; i < vFoodBanks.size(); ++i ) {
				double distance = sqrt(  ( ( x - vFoodBanks[i].x ) * ( x - vFoodBanks[i].x ) ) +
										( ( y - vFoodBanks[i].y ) * ( y - vFoodBanks[i].y ) ) );
				//convert distance from metres to km
				distance /= 1000;

				if( distance <= 1.0 ) {
					temp.oneToTwo++;
					//can't get closer than this so exit
					break;
				} else if( distance > 1.0 && distance <= 2.0 ) {
					temp.oneToTwo++;
				} else if( distance > 2.0 && distance <= 5.0 ) {
					temp.twoToFive++;
				} else {
					temp.greaterThanFive++;
				}		
			}

			//commit closest foodbank to master table
			if( temp.zeroToOne > 0 )
				ranges.zeroToOne++;
			else if( temp.oneToTwo > 0 )
				ranges.oneToTwo++;
			else if( temp.twoToFive > 0 )
				ranges.twoToFive++;
			else
				ranges.greaterThanFive++;
		}

		//print out report
		cout << "Results for " << nAddresses << " Addresses..." << endl << endl;

		cout << "Nearest Foodbank(km)" << setw(20) << "# of Addresses" << setw(20) << "% of Addresses" << endl;
		cout << "--------------------" << setw(20) << "--------------" << setw(20) << "--------------" << endl;
		cout << "\t\t0-1" << setw(20) << ranges.zeroToOne << setw(20) <<  static_cast<double>( ranges.zeroToOne ) / nAddresses << "%"<< endl;
		cout << "\t\t1-2" << setw(20) << ranges.oneToTwo << setw(20) << static_cast<double>( ranges.oneToTwo )/ nAddresses << "%"<< endl;
		cout << "\t\t2-5" << setw(20) << ranges.twoToFive << setw(20) << static_cast<double>( ranges.twoToFive ) / nAddresses << "%"<< endl;
		cout << "\t\t>5" << setw(20) << ranges.greaterThanFive << setw(20) << static_cast<double>( ranges.greaterThanFive ) / nAddresses << "%"<< endl;

	}

}